/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2009，所有权利保留。
 * 
 * 项目名：	rumba-widget2
 * 文件名：	RCaptionBar.java
 * 模块说明：	
 * 修改历史：
 * Feb 17, 2009 - lxm - 创建。
 */
package com.hd123.rumba.gwt.widget2.client.panel;

import java.util.ArrayList;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.hd123.rumba.gwt.widget2.client.misc.RImageLocation;

/**
 * 标题条，设计提供给{@link RCaptionBox}使用，作为其一部分。
 * <p>
 * 
 * <b>控件元素结构<b><br>
 * FlowPanel<br>
 * ..[SimplePanel class=icon] 显示图标<br>
 * ....Image <br>
 * ..HTML class=caption 显示标题<br>
 * ..[HorizontalPanel class=buttons] 客户按钮容器<br>
 * ....Widget[] 由调用者添加的其它项目，例如RToolbarButton。<br>
 * ..[div class=minimize] 最小化按钮<br>
 * ..[div class=restore] 还原按钮<br>
 * ..[div class=maximize] 最大化按钮<br>
 * ..[div class=close] 关闭按钮<br>
 * 
 * <b>CSS Style Rules</b>
 * <ol type=disc>
 * <li>.rb-CaptionBar {}</li>
 * <li>.rb-CaptionBar-solid { 填充状态 }</li>
 * <li>.rb-CaptionBar .icon { 图标 }</li>
 * <li>.rb-CaptionBar .caption { 标题 }</li>
 * <li>.rb-CaptionBar .seperator { 分割条 }</li>
 * <li>.rb-CaptionBar .minimize { 最小化按钮 }</li>
 * <li>.rb-CaptionBar .minimize-hovering { 最小化按钮，光标位于其上方时。 }</li>
 * <li>.rb-CaptionBar .restore { 还原按钮 }</li>
 * <li>.rb-CaptionBar .restore-hovering { 还原按钮，光标位于其上方时。 }</li>
 * <li>.rb-CaptionBar .maximize { 最大化按钮 }</li>
 * <li>.rb-CaptionBar .maximize-hovering { 最大化按钮，光标位于其上方时。 }</li>
 * <li>.rb-CaptionBar .close { 关闭按钮 }</li>
 * <li>.rb-CaptionBar .close-hovering { 关闭按钮，光标位于其上方时。 }</li>
 * <li>.rb-CaptionBar .buttons { 客户按钮容器 }</li>
 * </ol>
 * 
 * @author lxm
 * 
 */
public class RCaptionBar extends Composite {

  private static final String STYLENAME_DEFAULT = "rb-CaptionBar";

  /**
   * 创建对象实例。
   */
  public RCaptionBar() {
    super();
    drawSelf();
  }

  private FlowPanel pnl;
  private Helper_pnl pnlHelper;
  private RImageLocation icon;
  private boolean showMinimize = false;
  private boolean showMaximize = false;
  private boolean showClose = false;
  private boolean minimized = false;
  private boolean maximized = false;
  private boolean solid = false;
  /** 事件侦听器列表。List of RCaptionBarListener */
  private ArrayList listeners = new ArrayList();
  /** 包含的其它工具按钮。List of Widget */
  private ArrayList buttons = new ArrayList();

  private static final String CNAME_ICON = "icon";
  private static final String CNAME_CAPTION = "caption";
  private static final String CNAME_SEPERATOR = "seperator";
  private static final String CNAME_BUTTONS = "buttons";

  private static final int BTN_CLOSE = 0;
  private static final int BTN_MAXIMIZE = 1;
  private static final int BTN_RESTORE = 2;
  private static final int BTN_MINIMIZE = 3;
  private static final String[] CNAME_INNER = new String[] {
      "close", "maximize", "restore", "minimize" };
  private static final String[] TITLE_INNER = new String[] {
      "关闭", "最大化", "恢复", "最小化" };

  /**
   * 取得当前显示标题。
   * 
   * @return
   */
  public String getCaption() {
    if (!pnlHelper.isCreated(CNAME_CAPTION))
      return null;
    HTML html = (HTML) pnlHelper.getChild(CNAME_CAPTION);
    return html.getHTML();
  }

  /**
   * 设置当前显示标题。
   * 
   * @param caption
   */
  public void setCaption(String caption) {
    HTML html = (HTML) pnlHelper.getChild(CNAME_CAPTION);
    html.setHTML(caption);
  }

  /**
   * 取得当前显示图标。
   * 
   * @return
   */
  public RImageLocation getIcon() {
    return icon;
  }

  /**
   * 设置当前显示图标。
   * 
   * @param icon
   */
  public void setIcon(RImageLocation icon) {
    if (this.icon == icon)
      return;
    this.icon = icon;
    if (this.icon != null) {
      HTML html = (HTML) pnlHelper.getChild(CNAME_ICON);
      html.setHTML(this.icon.toHTML());
      html.setVisible(true);
    } else {
      if (!pnlHelper.isCreated(CNAME_ICON))
        return;
      HTML html = (HTML) pnlHelper.getChild(CNAME_ICON);
      html.setHTML("");
      html.setVisible(false);
    }
  }

  /**
   * 取得是否显示“最小化”按钮。
   * 
   * @return
   */
  public boolean isShowMinimize() {
    return showMinimize;
  }

  /**
   * 设置是否显示“最小化”按钮。
   * 
   * @param showMinimize
   */
  public void setShowMinimize(boolean showMinimize) {
    this.showMinimize = showMinimize;
    refreshInnerButtons();
    refreshSeperator();
  }

  /**
   * 取得是否显示“最大化”按钮。
   * 
   * @return
   */
  public boolean isShowMaximize() {
    return showMaximize;
  }

  /**
   * 设置是否显示“最大化”按钮。
   * 
   * @param showMaximize
   */
  public void setShowMaximize(boolean showMaximize) {
    this.showMaximize = showMaximize;
    refreshInnerButtons();
    refreshSeperator();
  }

  /**
   * 取得是否显示“关闭”按钮。
   * 
   * @return
   */
  public boolean isShowClose() {
    return showClose;
  }

  /**
   * 设置是否显示“关闭”按钮。
   * 
   * @param showClose
   */
  public void setShowClose(boolean showClose) {
    this.showClose = showClose;
    refreshInnerButtons();
    refreshSeperator();
  }

  /**
   * 取得是否填充。默认为false。
   * 
   * @return
   */
  public boolean isSolid() {
    return solid;
  }

  /**
   * 设置是否填充。默认为false。
   * 
   * @param solid
   */
  public void setSolid(boolean solid) {
    this.solid = solid;
    if (this.solid)
      addStyleDependentName("solid");
    else
      removeStyleDependentName("solid");
  }

  /**
   * 添加关于标题条控件的事件侦听器。
   * 
   * @param listener
   */
  public void addCaptionBarListener(RCaptionBarListener listener) {
    listeners.add(listener);
  }

  /**
   * 删除指定的关于标题条控件的事件侦听器
   * 
   * @param listener
   */
  public void removeCaptionBarListener(RCaptionBarListener listener) {
    listeners.remove(listener);
  }

  /**
   * 清除所有添加的按钮。
   */
  public void clearButtons() {
    if (pnlHelper.isCreated(CNAME_BUTTONS)) {
      HorizontalPanel pnlBtns = (HorizontalPanel) pnlHelper.getChild(CNAME_BUTTONS);
      for (int i = 0, n = buttons.size(); i < n; i++) {
        Widget button = (Widget) buttons.get(i);
        pnlBtns.remove(button);
      }
    }
    buttons.clear();
    refreshSeperator();
  }

  /**
   * 添加一个新的按钮。
   * 
   * @param button
   *            指定被添加的按钮。传入null或已经存在则忽略。
   */
  public void addButton(Widget button) {
    if (button == null)
      return;
    if (buttons.contains(button))
      return;

    buttons.add(button);

    HorizontalPanel pnlBtns = (HorizontalPanel) pnlHelper.getChild(CNAME_BUTTONS);
    pnlBtns.add(button);

    refreshSeperator();
  }

  /**
   * 插入指定的按钮。
   * 
   * @param button
   *            指定被添加的按钮。传入null或已经存在则忽略。
   * @param nextButton
   *            将被添加的按钮插入到指定按钮前。若传入null或者不存在的按钮，则等价于{@link #addButton(Widget)}。
   */
  public void insertButton(Widget button, Widget nextButton) {
    if (button == null)
      return;
    if (buttons.contains(button))
      return;
    if (nextButton == null || !buttons.contains(nextButton)) {
      addButton(button);
      return;
    }

    int idx = buttons.indexOf(nextButton);
    buttons.add(idx, button);

    HorizontalPanel pnlBtns = (HorizontalPanel) pnlHelper.getChild(CNAME_BUTTONS);
    int idx2 = pnlBtns.getWidgetIndex(nextButton);
    pnlBtns.insert(button, idx2);

    refreshSeperator();
  }

  /**
   * 删除指定的项目。
   * 
   * @param item
   *            指定被删除的项目，若传入的项目不存在则不作任何事。
   */
  public void removeButton(Widget button) {
    if (button == null)
      return;
    if (!buttons.contains(button))
      return;

    buttons.remove(button);

    HorizontalPanel pnlBtns = (HorizontalPanel) pnlHelper.getChild(CNAME_BUTTONS);
    pnlBtns.remove(button);

    refreshSeperator();
  }

  /**
   * 判断是否已经包含了指定的项目。
   * 
   * @param button
   *            指定的项目。
   * @return
   */
  public boolean containsButton(Widget button) {
    return buttons.contains(button);
  }

  /**
   * 取得当前是否最小化。
   * 
   * @return
   */
  boolean isMinimized() {
    return minimized;
  }

  /**
   * 取得当前是否最大化。
   * 
   * @return
   */
  boolean isMaximized() {
    return maximized;
  }

  /**
   * 执行标题条控件最大化处理。
   */
  void maximizeSize() {
    maximized = true;
    minimized = false;
    refreshInnerButtons();
  }

  /**
   * 执行标题条控件最小化处理。
   */
  void minimizeSize() {
    maximized = false;
    minimized = true;
    refreshInnerButtons();
  }

  /**
   * 执行标题条控件还原处理。
   */
  void doRestoreSize() {
    maximized = false;
    minimized = false;
    refreshInnerButtons();
  }

  private void drawSelf() {
    pnl = new FlowPanel();
    pnl.setWidth("100%");
    pnlHelper = new Helper_pnl();

    pnlHelper.appendChild(CNAME_ICON, true);
    pnlHelper.appendChild(CNAME_CAPTION, true);
    for (int i = 0, n = CNAME_INNER.length; i < n; i++)
      pnlHelper.appendChild(CNAME_INNER[i], true);
    pnlHelper.appendChild(CNAME_SEPERATOR, false);
    pnlHelper.appendChild(CNAME_BUTTONS, true);

    initWidget(pnl);
    setStyleName(STYLENAME_DEFAULT);
  }

  /** 刷新内建按钮的显示。 */
  private void refreshInnerButtons() {
    showInnerButton(CNAME_INNER[BTN_CLOSE], showClose);
    showInnerButton(CNAME_INNER[BTN_MAXIMIZE], showMaximize && maximized == false);
    showInnerButton(CNAME_INNER[BTN_MINIMIZE], showMinimize && minimized == false);
    showInnerButton(CNAME_INNER[BTN_RESTORE], (showMaximize || showMinimize)
        && (maximized || minimized));
  }

  /** 刷新分隔条的显示。 */
  private void refreshSeperator() {
    SimplePanel pnl = (SimplePanel) pnlHelper.getChild(CNAME_SEPERATOR);

    boolean showInner = showClose || showMaximize || showMinimize;
    if (!showInner) {
      pnl.setVisible(false);
      return;
    }

    boolean showButtons = buttons.size() > 0;
    pnl.setVisible(showButtons);
  }

  /** 设置指定的内建按钮是否显示。 */
  private void showInnerButton(String childName, boolean show) {
    if (show) {
      InnerButton btn = (InnerButton) pnlHelper.getChild(childName);
      btn.setVisible(true);
    } else {
      if (pnlHelper.isCreated(childName)) {
        InnerButton btn = (InnerButton) pnlHelper.getChild(childName);
        btn.setVisible(false);
      }
    }
  }

  private void fireClose() {
    for (int i = 0, n = listeners.size(); i < n; i++) {
      RCaptionBarListener listener = (RCaptionBarListener) listeners.get(i);
      if (listener == null)
        continue;
      listener.onClose(this);
    }
  }

  private void fireMaximize() {
    for (int i = 0, n = listeners.size(); i < n; i++) {
      RCaptionBarListener listener = (RCaptionBarListener) listeners.get(i);
      if (listener == null)
        continue;
      listener.onMaximize(this);
    }
  }

  private void fireMinimize() {
    for (int i = 0, n = listeners.size(); i < n; i++) {
      RCaptionBarListener listener = (RCaptionBarListener) listeners.get(i);
      if (listener == null)
        continue;
      listener.onMinimize(this);
    }
  }

  private void fireRestore() {
    for (int i = 0, n = listeners.size(); i < n; i++) {
      RCaptionBarListener listener = (RCaptionBarListener) listeners.get(i);
      if (listener == null)
        continue;
      listener.onRestore(this);
    }
  }

  private class Helper_pnl extends FlowPanelHelper {

    public Helper_pnl() {
      super(pnl);
    }

    protected Widget createChild(String childName) {
      if (CNAME_ICON.equals(childName)) {
        HTML html = new HTML();
        html.setStyleName("icon");
        return html;
      }

      if (CNAME_CAPTION.equals(childName)) {
        HTML html = new HTML();
        html.setStyleName("caption");
        return html;
      }

      for (int i = 0, n = CNAME_INNER.length; i < n; i++) {
        if (CNAME_INNER[i].equals(childName)) {
          InnerButton btn = new InnerButton(i);
          return btn;

        }
      }

      if (CNAME_SEPERATOR.equals(childName)) {
        SimplePanel pnl = new SimplePanel();
        pnl.setStyleName("seperator");
        pnl.setVisible(false);
        return pnl;
      }

      if (CNAME_BUTTONS.equals(childName)) {
        HorizontalPanel pnl = new HorizontalPanel();
        pnl.setSpacing(0);
        pnl.setStyleName("buttons");
        return pnl;
      }

      return null;
    }
  }

  /**
   * 内建按钮
   * 
   * @author lxm
   * 
   */
  private class InnerButton extends Widget {

    public InnerButton(int btnIndex) {
      super();
      setElement(DOM.createDiv());
      DOM.setInnerText(getElement(), " ");
      setStyleName(CNAME_INNER[btnIndex]);
      setTitle(TITLE_INNER[btnIndex]);
      sinkEvents(Event.MOUSEEVENTS | Event.ONCLICK);
    }

    public void onBrowserEvent(Event event) {
      super.onBrowserEvent(event);

      switch (DOM.eventGetType(event)) {
      case Event.ONCLICK:
        doClick();
        break;
      case Event.ONMOUSEOVER:
        addStyleDependentName("hovering");
        break;
      case Event.ONMOUSEOUT:
        removeStyleDependentName("hovering");
        break;
      }
    }

    private void doClick() {
      String s = getStylePrimaryName();
      if (CNAME_INNER[BTN_CLOSE].equals(s))
        fireClose();
      else if (CNAME_INNER[BTN_MAXIMIZE].equals(s))
        fireMaximize();
      else if (CNAME_INNER[BTN_RESTORE].equals(s))
        fireRestore();
      else if (CNAME_INNER[BTN_MINIMIZE].equals(s))
        fireMinimize();
    }

  }
}
